Skip to content

Conversation

@mmagician
Copy link
Collaborator

@mmagician mmagician commented Jan 23, 2026

As per the discussion here, the network target account ID is placed into NoteAttachment instead.

While at it, I created a helper function, similarly to the one we have for CLAIM notes: create_b2agg_note, and refactored the tests to use that utility.

TODO:

closes #2173
closes #2189

@mmagician mmagician force-pushed the mmagician-bagg-check branch from 69ed247 to bec68d1 Compare January 24, 2026 11:08
@mmagician mmagician marked this pull request as ready for review January 24, 2026 15:03
Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you! I left some comments inline. Also, I think it may make sense to merge this PR after #2338.

const ERR_B2AGG_TARGET_ACCOUNT_MISMATCH="B2AGG note attachment target account does not match consuming account"


#! Bridge-to-AggLayer (B2AGG) note script: bridges assets from Miden to an AggLayer-connected chain.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: let's add NOTE SCRIPT section header above this line.

#! - If the consuming account is the sender (reclaim): the note's assets are added back to the consuming account.
#! - If the consuming account is the Agglayer Bridge: the note's assets are moved to a BURN note,
#! and the note details are hashed into a leaf and appended to the Local Exit Tree.
#! global exit root (GER) merkle tree structure.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This statement seems to be dangling (and not sure if it is relevant here).

Comment on lines +65 to +76
# Ensure note attachment targets the consuming bridge account.
exec.active_note::get_metadata
# => [NOTE_ATTACHMENT, METADATA_HEADER, pad(8)]

# TODO simplify once https://github.com/0xMiden/miden-base/pull/2338 lands

swapw dropw
# => [NOTE_ATTACHMENT, pad(12)]

# Reorder attachment word to [target_id_prefix, target_id_suffix].
drop drop
# => [target_id_prefix, target_id_suffix, pad(14)] (auto-padding)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I would move this into a helper procedure. This way, once #2338 land, we can just replace the procedure name here. Although, it may make sense to merge this one after #2338 lands (or based this PR on #2338).

const ERR_UPDATE_GER_UNEXPECTED_NUMBER_OF_STORAGE_ITEMS = "UPDATE_GER script expects exactly 8 note storage items"
const ERR_UPDATE_GER_TARGET_ACCOUNT_MISMATCH = "UPDATE_GER note attachment target account does not match consuming account"

#! Agglayer Bridge UPDATE_GER script: updates the GER by calling the bridge_in::update_ger function.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: let's add NOTE SCRIPT section header above this line.

Comment on lines +33 to +35
/// Contains the destination network and address information required
/// for bridging assets to the AggLayer network.
#[derive(Debug, Clone)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: comment wrapping.

/// Destination network identifier (AggLayer-assigned network ID)
pub destination_network: u32,
/// Destination Ethereum address (20 bytes)
pub destination_address: EthAddressFormat,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (and not related to this PR): I think we should call it just EthAddress rather than EthAddressFormat.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It used to be call EthAddress, but was renamed as per #2238 (comment)

However, this was in the light of bridging-in, where we were passing a 160 bit value that was represented as an address on Ethereum, but was in fact encoding a Miden AccountId - i.e. it was not a "valid" Ethereum address ("valid" in the sense that there was no account associated with it).

In the bridging out flow, the value carried by the B2AGG note will actually be a valid Ethereum destination address.


I wouldn't change the naming to EthAddress (because it is not strictly correct) across the board.
I think the best solution here is to:

  1. create a separate EthAddress dedicated for the bridging-out flow. It also wouldn't have methods such as from_account_id(account_id: AccountId) as they don't make sense there.
  2. keep EthAddress as the base struct, and create a EthAddressFormat trait to encompass Miden<>Ethereum conversion logic like from_account_id / from_account_id

WDYT?

Comment on lines +84 to +90
/// # Parameters
/// - `storage`: The destination network and address information
/// - `assets`: The assets to bridge (must be fungible assets from a network faucet)
/// - `target_account_id`: The account ID that will consume this note (bridge account)
/// - `sender_account_id`: The account ID of the note creator
/// - `note_type`: The type of note (Public or Private)
/// - `rng`: Random number generator for creating the note serial number
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need note_type here? I think B2AGG notes would have to always be public (otherwise, the bridge can't process them).

let tag = NoteTag::new(0);

let attachment = NoteAttachment::from(
NetworkAccountTarget::new(target_account_id, NoteExecutionHint::None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use NoteExecutionHint::Always here because B2AGG notes are always consumable.


let bridge_out_component = bridge_out_component(vec![]);
// Create the "bridge_out" component
let let_storage_slot_name = StorageSlotName::new("miden::agglayer::let").unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe not for this PR, but we should normalize storage slot naming. For example, this should be miden::agglayer::bridge::let to be consistent with miden::agglayer::bridge::ger_upper and miden::agglayer::bridge::ger_lower (which I think should be just one slot miden::agglayer::bridge::ger).

Copy link
Contributor

@PhilippGackstatter PhilippGackstatter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me (only reviewed the note attachment parts - let me know if you want me to review everything).

///
/// # Errors
/// Returns an error if note creation fails.
pub fn create_b2agg_note<R: FeltRng>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: For future note creation functions, I think we should directly implement the approach described in #2283, since we'll have to migrate all standard note types to this approach anyway.

let b2agg_script = b2agg_script();
let recipient = NoteRecipient::new(
rng.draw_word(),
miden_protocol::note::NoteScript::new(b2agg_script),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
miden_protocol::note::NoteScript::new(b2agg_script),
NoteScript::new(b2agg_script),

Nit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants